// Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved.
// This source file is part of the Cangjie project, licensed under Apache-2.0
// with Runtime Library Exception.
//
// See https://cangjie-lang.cn/pages/LICENSE for license information.

#ifndef CANGJIE_MIGRATOR_RULES_EXTRACTED_INFO
#define CANGJIE_MIGRATOR_RULES_EXTRACTED_INFO

#include <string>
#include <vector>
#include <variant>

#include "cangjie/AST/Node.h"

#include "PositionRange.h"
#include "MatchRule.h"

namespace CangjieMigrator::Rules {

class ExtractedInfo {
public:
    PositionRange replacePosition;
    const Cangjie::AST::Node &node;

    explicit ExtractedInfo(PositionRange replacePosition, const Cangjie::AST::Node &node);
    virtual ~ExtractedInfo() = default;

    [[nodiscard]] virtual MatchRule::Type GetType() const = 0;
    [[nodiscard]] virtual std::string ToString() const = 0;
};

class Argument {
private:
    std::variant<PositionRange, std::string> value;

public:
    explicit Argument(const PositionRange& range);

    explicit Argument(const std::string& str);

    [[nodiscard]] bool IsRange() const;

    [[nodiscard]] bool IsString() const;

    [[nodiscard]] const PositionRange &GetRange() const;

    [[nodiscard]] const std::string &GetString() const;
};

class CallExprExtractedInfo : public ExtractedInfo {
public:
    std::string funcName;
    std::string packageAndIdentifier;
    std::string funcType;
    PositionRange callerPositionRange; // $e
    std::vector<Argument> arguments; // $n

    CallExprExtractedInfo(PositionRange replacePosition, const Cangjie::AST::Node &node,
        const std::string &funcName,
        const std::string &packageAndIdentifier,
        const std::string &funcType,
        const PositionRange &callerPositionRange,
        std::vector<Argument> arguments);

    [[nodiscard]] MatchRule::Type GetType() const override;
    [[nodiscard]] std::string ToString() const override;
};

class MemberAccessExtractedInfo final : public ExtractedInfo {
public:
    std::string member;
    std::string packageAndIdentifier;
    PositionRange memberPositionRange;

    MemberAccessExtractedInfo(PositionRange replacePosition, const Cangjie::AST::Node &node,
        std::string member,
        std::string packageAndIdentifier,
        PositionRange memberPositionRange);

    [[nodiscard]] MatchRule::Type GetType() const override;
    [[nodiscard]] std::string ToString() const override;
};

class RefExprExtractedInfo final : public ExtractedInfo {
public:
    std::string package;
    std::string identifier;

    RefExprExtractedInfo(PositionRange replacePosition, const Cangjie::AST::Node &node, std::string package, std::string identifier);

    [[nodiscard]] MatchRule::Type GetType() const override;
    [[nodiscard]] std::string ToString() const override;
};

class TypeNameExtractedInfo final : public ExtractedInfo {
public:
    std::string package;
    std::string typeName;

    TypeNameExtractedInfo(PositionRange replacePosition, const Cangjie::AST::Node &node, std::string package, std::string typeName);

    [[nodiscard]] MatchRule::Type GetType() const override;
    [[nodiscard]] std::string ToString() const override;
};

class LetAsPatternExtractedInfo final : public ExtractedInfo {
public:
    LetAsPatternExtractedInfo(PositionRange replacePosition, const Cangjie::AST::Node &node);

    [[nodiscard]] MatchRule::Type GetType() const override;
    [[nodiscard]] std::string ToString() const override;
};

} // namespace CangjieMigrator::Rules

#endif // CANGJIE_MIGRATOR_RULES_EXTRACTED_INFO